package cn.tlb.gl.demo2;

import android.opengl.GLSurfaceView.Renderer;
import android.view.MotionEvent;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

/**
 * Created by 汤林冰 on 2015/12/9 10:36.
 */
public class MyRender implements Renderer {
    // triangle
    // 定义平面三角形的三个顶点初始坐标(坐标系的绘制范围见onSurfaceChanged中指定)
    //空间中的点由(x,y,z)坐标指定, opengl中的坐标系和笛卡尔坐标系一致
    //绘制的三角形在z=0的平面上
    float[] triangle = {
       0.1f, 0.6f, 0f,
      -0.3f, 0.0f, 0f,
       0.3f, 0.1f, 0f
    };

    //定义三角形每个顶点的颜色,自动将中间区域的颜色使用过渡色填充
    //颜色值有4个分量, 分别为 RGBA分量, 每个分量都是int类型
    int[] triangleColors = {
      65535, 0, 0, 0,       // rgba: top vertex color  RED
      0, 65535, 0, 0,       // GREEN
      0, 0, 65535, 0       //BLUE
    };


    // squear
    float[] squear1 = {
         0.4f, 0.4f, 0,
         0.4f, -0.4f, 0,
         -0.4f, 0.4f, 0,
         -0.4f, -0.4f, 0
    };
    int[] squear1Colors = {
            0xFFFF, 0, 0, 0,
            0, 0xFFFF, 0, 0,
            0, 0, 0xFFFF, 0,
            0xFFFF, 0xFFFF, 0, 0
    };

    // polygon
    float[] squear2 = {
            -0.4f, 0.4f, 0,
            0.4f, 0.4f, 0,
            0.4f, -0.4f, 0,
            -0.4f, -0.4f, 0
    };
    int[] squear2Colors = {
            0xFFFF, 0, 0, 0,
            0, 0xFFFF, 0, 0,
            0, 0, 0xFFFF, 0,
            0xFFFF, 0xFFFF, 0, 0
    };

    float[] polygon = {
            0.4f, 0.4f, 0,
            -0.2f, 0.3f, 0,
            0.5f, 0, 0,
            -0.4f, 0, 0,
            -0.1f, -0.3f, 0
    };

    FloatBuffer triangleVertexes;
    IntBuffer triangleColorBuffer;
    FloatBuffer squear1Vertexes;
    IntBuffer squear1ColorBuffer;
    FloatBuffer squear2Vertexes;
    IntBuffer squear2ColorBuffer;

    float rotate = 0;

    public MyRender() {
        // OpenGL API接口需要使用Buffer绘制图形顶点和颜色,
        // 使用的Buffer必须是native order 的 direct buffer. 关键代码:
        // ------------- 使用 float[] 生成 FloatBuffer ----------------
        // ByteBuffer byteBuffer = ByteBuffer.allocateDirect(fs.length * 4);
        // byteBuffer.order(ByteOrder.nativeOrder());
        // FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
        // -----------------------------------------------------------
        triangleVertexes = array2FloatBuffer(triangle);
        triangleColorBuffer = array2IntBuffer(triangleColors);
        squear1Vertexes = array2FloatBuffer(squear1);
        squear1ColorBuffer = array2IntBuffer(squear1Colors);
        squear2Vertexes = array2FloatBuffer(squear2);
        squear2ColorBuffer = array2IntBuffer(squear2Colors);
    }

    MotionEvent event;
    float touchX;
    float touchY;

    float rotateX;
    float rotateY;

    public void setEvent(MotionEvent event) {
        this.event = event;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // 禁用抖动
        gl.glDisable(GL10.GL_DITHER);
        // 修正系统透视
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
        // 使用指定颜色清屏
        gl.glClearColor(0, 0, 0, 0);
        // 阴影样式:光滑
        gl.glShadeModel(GL10.GL_SMOOTH);
        // 开启深度测试
        gl.glEnable(GL10.GL_DEPTH_TEST);
        // 深度测试模式, 显示z<=1.0的所有物体
        gl.glDepthFunc(GL10.GL_LEQUAL);
    }

    /**
     * @param gl
     * @param width
     * @param height
     */
    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glViewport(0, 0, width, height);
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        float ratio = (float)width/height;
        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
    }



    @Override
    public void onDrawFrame(GL10 gl) {
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        gl.glMatrixMode(GL10.GL_MODELVIEW);

        //-----------triangle----------
        //初始化矩阵, 是当前的模型矩阵为单位阵, 如果不重置,经过若干次变换后的图形将是难以预测的
        gl.glLoadIdentity();
        // 平移变换, 这里如果z>=1,将看不到图形
        gl.glTranslatef(-0.6f, 0.6f, -3f);
        if(event != null) {
            switch(event.getAction()){
                case MotionEvent.ACTION_DOWN:
                    touchX = event.getX();
                    touchY = event.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    rotateX += (event.getX()-touchX)/20;
                    rotateY += ((event.getY()-touchY))/20;
                    break;
                default:
                    break;
            }
        }
        // 触摸屏幕旋转图形
        gl.glRotatef(rotateY, 0.2f, 0, 0);// 垂直方向移动, 绕x轴旋转
        gl.glRotatef(rotateX, 0, 0.2f, 0);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, triangleVertexes);
        gl.glColorPointer(4, GL10.GL_FIXED, 0, triangleColorBuffer);
        gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);

        //-----------------------------------
        gl.glLoadIdentity();
        gl.glTranslatef(0.5f, 0.9f, -1.5f);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, squear1Vertexes);
        gl.glColorPointer(4, GL10.GL_FIXED, 0, squear1ColorBuffer);
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);

        //---------------------------------------------
        gl.glLoadIdentity();
        gl.glTranslatef(-0.4f, -0.2f, -1.5f);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, squear2Vertexes);
        gl.glColorPointer(4, GL10.GL_FIXED, 0, squear2ColorBuffer);
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);


        //-----------------多边形------------------
        gl.glLoadIdentity();
        gl.glTranslatef(0.5f, -0.5f, -1.5f);

        gl.glColor4f(1f, .2f, 1f, 0f);
        gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, array2FloatBuffer(polygon));
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 5);

        gl.glFinish();
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        rotate ++;
    }


    private FloatBuffer array2FloatBuffer(float fs[]){
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(fs.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
        FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
        floatBuffer.put(fs);
        floatBuffer.position(0);
        return floatBuffer;
    }

    private IntBuffer array2IntBuffer(int ints[]){
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(ints.length*4);
        byteBuffer.order(ByteOrder.nativeOrder());
        IntBuffer intBuffer = byteBuffer.asIntBuffer();
        intBuffer.put(ints);
        intBuffer.position(0);
        return intBuffer;
    }
}
